type MessageHandler = (data: any) => void;

/**
 * WebSocket 客户端管理类
 */
export class WebSocketClient {
  private ws: WebSocket | null = null;
  private url: string;
  private reconnectTimer: NodeJS.Timeout | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectInterval = 3000;
  private messageHandlers: Map<string, Set<MessageHandler>> = new Map();
  private isManualClose = false;

  constructor(url: string) {
    this.url = url;
  }

  /**
   * 连接 WebSocket
   */
  connect(token: string) {
    try {
      const wsUrl = `${this.url}?token=${token}`;
      console.log('正在连接 WebSocket:', wsUrl.replace(token, 'TOKEN_HIDDEN'));
      
      this.ws = new WebSocket(wsUrl);

      this.ws.onopen = () => {
        console.log('✅ WebSocket 已连接');
        this.reconnectAttempts = 0;
        this.isManualClose = false;
        
        // 触发连接成功的内部事件
        this.handleMessage({
          type: 'ws_opened',
          message: 'WebSocket connection established',
          timestamp: Date.now(),
        });
      };

      this.ws.onmessage = (event) => {
        try {
          const message = JSON.parse(event.data);
          console.log('📩 收到 WebSocket 消息:', message.type);
          this.handleMessage(message);
        } catch (error) {
          console.error('❌ 解析 WebSocket 消息失败:', error);
        }
      };

      this.ws.onerror = (error) => {
        console.error('❌ WebSocket 连接错误:', error);
        console.error('WebSocket URL:', this.url);
      };

      this.ws.onclose = (event) => {
        console.log('🔌 WebSocket 已断开', {
          code: event.code,
          reason: event.reason,
          wasClean: event.wasClean
        });
        if (!this.isManualClose) {
          this.reconnect(token);
        }
      };
    } catch (error) {
      console.error('❌ WebSocket 连接失败:', error);
    }
  }

  /**
   * 重新连接
   */
  private reconnect(token: string) {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error('WebSocket 重连失败，已达到最大重连次数');
      return;
    }

    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
    }

    this.reconnectTimer = setTimeout(() => {
      console.log(`尝试重新连接 WebSocket (${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`);
      this.reconnectAttempts++;
      this.connect(token);
    }, this.reconnectInterval);
  }

  /**
   * 发送消息
   */
  send(data: any) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(data));
    } else {
      console.warn('WebSocket 未连接，无法发送消息');
    }
  }

  /**
   * 订阅消息类型
   */
  subscribe(type: string, handler: MessageHandler) {
    if (!this.messageHandlers.has(type)) {
      this.messageHandlers.set(type, new Set());
    }
    this.messageHandlers.get(type)!.add(handler);
  }

  /**
   * 取消订阅
   */
  unsubscribe(type: string, handler: MessageHandler) {
    const handlers = this.messageHandlers.get(type);
    if (handlers) {
      handlers.delete(handler);
      if (handlers.size === 0) {
        this.messageHandlers.delete(type);
      }
    }
  }

  /**
   * 处理接收到的消息
   */
  private handleMessage(message: any) {
    const { type, data } = message;
    const handlers = this.messageHandlers.get(type);
    if (handlers) {
      handlers.forEach((handler) => {
        try {
          handler(data || message);
        } catch (error) {
          console.error(`处理消息失败 (type: ${type}):`, error);
        }
      });
    }
  }

  /**
   * 关闭连接
   */
  close() {
    this.isManualClose = true;
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  /**
   * 获取连接状态
   */
  isConnected() {
    return this.ws?.readyState === WebSocket.OPEN;
  }
}

// 创建全局 WebSocket 客户端实例
const getWebSocketUrl = () => {
  // 从 API 基础 URL 获取 host
  const apiBaseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:4321/api';
  const url = new URL(apiBaseUrl);
  
  // 根据 API 的协议决定 WebSocket 协议
  const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
  
  // 构建 WebSocket URL
  return `${protocol}//${url.host}/ws`;
};

export const wsClient = new WebSocketClient(getWebSocketUrl());

